import type { EnumConfig, EnumItem } from './types/enum'

import { nextTick, type Ref, ref } from 'vue'
import { enumManager } from './utils/enum-manager'

interface UseEnumConfig extends EnumConfig {
  immediate?: boolean
  forceRefresh?: boolean // 是否需要刷新缓存
}

interface EnumReturn {
  loading: Ref<boolean>
  error: Ref<string>
  load: (forceRefresh?: boolean) => Promise<void>
  refresh: () => Promise<void>
  getLabel: (enumKey: string, value: string | number) => string
  getValue: (enumKey: string, label: string) => string | number | undefined
  [key: string]: any
}

export function useEnum(keys: string | string[], config: UseEnumConfig = {}): EnumReturn {
  const loading = ref(false)
  const error = ref('')
  const enumKeys = Array.isArray(keys) ? keys : [keys]

  const reactiveEnums: Record<string, Ref<EnumItem[]>> = {}
  enumKeys.forEach(key => {
    // 初始时总是创建一个空的 ref
    reactiveEnums[key] = ref([])
  })

  const load = async (isManualRefresh = false) => {
    loading.value = true
    error.value = ''

    try {
      // 决定是否需要强制刷新
      const shouldForceRefresh = isManualRefresh || config.forceRefresh

      let result: Record<string, EnumItem[]>
      if (shouldForceRefresh) {
        // 如果需要刷新，调用 refreshEnums
        result = await enumManager.refreshEnums(enumKeys, config)
      } else {
        // 否则，调用 getEnums (会使用缓存)
        result = await enumManager.getEnums(enumKeys, config)
      }

      // 用返回的结果更新我们的响应式 ref
      enumKeys.forEach(key => {
        reactiveEnums[key].value = result[key] || []
      })
    } catch (err) {
      error.value = err instanceof Error ? err.message : '获取枚举失败'
      console.error(`获取批量枚举失败: ${enumKeys.join(', ')}`, err)
    } finally {
      loading.value = false
    }
  }

  const refresh = () => load(true)

  const getLabel = (enumKey: string, value: string | number): string => {
    const enumData = reactiveEnums[enumKey]?.value || []
    // 使用 '==' 进行比较，可以同时处理数字和字符串类型的 value
    const item = enumData.find(item => item.value == value)
    return item?.label || String(value)
  }

  const getValue = (enumKey: string, label: string): string | number | undefined => {
    const enumData = reactiveEnums[enumKey]?.value || []
    const item = enumData.find(item => item.label === label)
    return item?.value
  }

  const { immediate = true } = config

  if (immediate) {
    nextTick(load)
  }

  return {
    ...reactiveEnums,
    loading,
    error,
    load,
    refresh,
    getLabel,
    getValue,
  }
}
